#pragma once

#include <jsoncpp/json/json.h>
#include <assert.h>
#include "include/mysql.h"
#include "../comm/Log.hpp"

namespace ns_database
{

    class DataBase
    {
    public:
        DataBase()
        {
            //初始化mysql操作句柄
            _mfp = mysql_init(nullptr);
            assert(ConnectMysql());
            pthread_mutex_init(&_mtx, nullptr);
        }
        ~DataBase()
        {
            //关闭连接
            mysql_close(_mfp);
            pthread_mutex_destroy(&_mtx);
        }
        bool ConnectMysql()
        {
            if (nullptr == mysql_real_connect(_mfp, "127.0.0.1", "oj", "******", "oj", 3306, nullptr, 0))
            {
                LOG(FATAL, "连接数据库失败");
                return false; // 给开发人员看
            }
            mysql_set_character_set(_mfp, "utf8");
            LOG(INFO, "连接数据库成功");
            return true;
        }
        std::string GetUserName(int id, const std::string &strId, const std::string &table)
        {
            std::string sql = "select user from " + table + " where " + strId + " = ";
            sql += std::to_string(id) + ";";
            // std::cout << sql << std::endl;
            int ret = mysql_query(_mfp, sql.c_str());
            if (ret != 0)
            {
                LOG(WARINNG, sql + " 执行失败");
                return ""; // 给开发人员看
            }
            // 提取结果
            MYSQL_RES *result = mysql_store_result(_mfp);
            // 分析结果
            int row = mysql_num_rows(result);
            if (row == 0)
            {
                LOG(ERROR, "无结果");
                return "";
            }
            MYSQL_ROW line = mysql_fetch_row(result);

            free(result);
            return line[0];
        }
        void AddQuestion(const std::string &in_json, std::string &out_json)
        {
            // 1.获取用户信息
            Json::Value in_value;
            Json::Reader reader;
            reader.parse(in_json, in_value);
            std::string title = in_value["title"].asString();
            std::string level = in_value["level"].asString();
            std::string desc = in_value["desc"].asString();
            std::string header = in_value["header"].asString();
            std::string body = in_value["body"].asString();
            std::string tail = in_value["tail"].asString();
            std::string cpu_limit = in_value["cpu"].asString();
            std::string mem_limit = in_value["mem"].asString();
            std::string sql = "insert into oj_questions(title, level, `desc`, `header`, `body`, `tail`, cpu_limit, mem_limit) values('";
            sql += title + "', '";
            sql += level + "', '";
            sql += desc + "', '";
            sql += header + "', '";
            sql += body + "', '";
            sql += tail + "', ";
            sql += cpu_limit + ", ";
            sql += mem_limit + ");";
            // LOG(INFO, sql);
            Json::Value out_value;
            if (Insert(sql))
            {
                LOG(INFO, "题目添加成功");
                out_value["result"] = "success";
            }
            else
            {
                LOG(INFO, "题目添加失败");
                out_value["result"] = "fail";
            }
            Json::FastWriter writer;
            out_json = writer.write(out_value);
        }
        bool QueryMysql(const std::string &sql, MYSQL_RES *&result)
        {
            pthread_mutex_lock(&_mtx);
            int ret = mysql_query(_mfp, sql.c_str());
            if (ret != 0)
            {
                LOG(WARINNG, sql + " 执行失败");
                perror("执行失败");
                return false;
            }
            // 提取结果
            result = mysql_store_result(_mfp);
            pthread_mutex_unlock(&_mtx);
            return true;
        }
        bool Insert(const std::string &sql)
        {
            int ret = mysql_query(_mfp, sql.c_str());
            if (ret != 0)
            {
                LOG(WARINNG, sql + " 执行失败");
                return false; // 给开发人员看
            }
            return true;
        }
        int Select(const std::string &sql, const std::string &password, std::string &out)
        {
            // std::cout << sql << std::endl;
            int ret = mysql_query(_mfp, sql.c_str());
            if (ret != 0)
            {
                LOG(WARINNG, sql + " 执行失败");
                return -1; // 给开发人员看
            }
            // 提取结果
            MYSQL_RES *result = mysql_store_result(_mfp);
            // 分析结果
            int row = mysql_num_rows(result);
            if (row == 0)
            {
                out = "1";
                return -2;
            }
            MYSQL_ROW line = mysql_fetch_row(result);
            if (line[2] != password)
            {
                out = "2";
                return -3;
            }
            out = "0";
            free(result);
            return atoi(line[0]);
        }

        bool Update(const std::string &sql, std::string &out)
        {
            // std::cout << sql << std::endl;
            int ret = mysql_query(_mfp, sql.c_str());
            if (ret != 0)
            {
                LOG(WARINNG, sql + " 执行失败");
                return false; // 给开发人员看
            }
            out = "0";
            return true;
        }

    private:
        MYSQL *_mfp;
        pthread_mutex_t _mtx;
    };
}
